package md.mru.frontend.beans;

import md.mru.frontend.convertors.ObjectMappingConverter;
import org.springframework.context.annotation.PropertySource;

import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * @author sergiu.marin
 * @since 29.03.2014
 */
@PropertySource("classpath:application.properties")
@SessionScoped
public class BackingBean implements Serializable {

    @ManagedProperty(value = "#{objectMappingConverter}")
    private ObjectMappingConverter objectMappingConverter;

    protected String constructOnCompleteScript(String formId, String tableId, String editRowId) {
        return "$(PrimeFaces.escapeClientId('" + formId + ":" + tableId + ":0:" + editRowId + "'))" +
                ".find('span.ui-icon-pencil').trigger('click');";
    }

    /**
     * Add message from properties file to context
     *
     * @param messageKey the key of the message
     * @param param      a parameter value to be replaced in the body of the message
     */
    protected void addErrorMessage(String messageKey, Object param) {
        addMessage(messageKey, param, FacesMessage.SEVERITY_ERROR);
    }

    /**
     * Add message from properties file to context
     *
     * @param uiInput           the input object
     * @param messageKeySummary the key of the message
     * @param messageKeyDetail  the key of the message
     * @param params            parameter values to be replaced in the body of the message
     */
    protected void addErrorMessage(UIOutput uiInput, String messageKeySummary, String messageKeyDetail, Object[] params) {
        addMessage(uiInput, messageKeySummary, messageKeyDetail, params, FacesMessage.SEVERITY_ERROR);
    }

    /**
     * Add message from properties file to context
     *
     * @param messageKey the key of the message
     * @param param      a parameter value to be replaced in the body of the message
     */
    protected void addInfoMessage(String messageKey, Object param) {
        addMessage(messageKey, param, FacesMessage.SEVERITY_INFO);
    }

    /**
     * Add message from properties file to context
     *
     * @param messageKey the key of the message
     * @param param      parameter value to be replaced in the body of the message
     * @param severity   severity level
     */
    protected void addMessage(String messageKey, Object param, FacesMessage.Severity severity) {
        String msg = getMessage(messageKey, param);

        if (msg != null && msg.indexOf("MISSING") >= 0) {
            msg = getMessage("error", null);
        }
        FacesMessage facesMsg = new FacesMessage(severity, msg, msg);

        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, facesMsg);
    }

    /**
     * @param uiInput           the component
     * @param messageKeySummary the key of the message
     * @param messageKeyDetail  the detail key of th emessage
     * @param detailParams      parameter values to be replaced in the body of the message
     * @param severity          severity level
     */
    private void addMessage(UIOutput uiInput, String messageKeySummary, String messageKeyDetail, Object[] detailParams,
                            FacesMessage.Severity severity) {
        String msgSummary = getMessage(messageKeySummary);
        String msgDetail = getMessage(messageKeyDetail, detailParams);

        FacesMessage facesMsg = new FacesMessage(severity, msgSummary, msgDetail);

        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(uiInput.getClientId(context), facesMsg);
    }

    /**
     * @param key the message key
     * @return the messages (String)
     */
    protected String getMessage(String key) {
        return getMessage(key, null);
    }

    protected String getMessage(String key, Object param) {
        FacesContext context = FacesContext.getCurrentInstance();
        Locale locale = context.getViewRoot().getLocale();
        return getMessage(key, param, locale);
    }

    /**
     * @param key   the message key
     * @param param the parameter for the message
     * @return the messages (String)
     */
    protected String getMessage(String key, Object param, Locale locale) {
        String message;

        try {
            FacesContext context = FacesContext.getCurrentInstance();
            Application application = context.getApplication();
            String messageBundleName = application.getMessageBundle();
            ResourceBundle resourceBundle = ResourceBundle.getBundle(messageBundleName);
            String msgPattern = resourceBundle.getString(key);

            if (param != null) {
                Object[] params;
                if (param instanceof Object[]) {
                    params = (Object[]) param;
                } else {
                    params = new Object[]{param};
                }
                String doubledApostrophes = "";
                for (int i = 0; i < msgPattern.length(); i++) {
                    char chr = msgPattern.charAt(i);
                    if (chr == '\'') {
                        doubledApostrophes += "\'\'";
                    } else {
                        doubledApostrophes += chr;
                    }
                }
                message = MessageFormat.format(doubledApostrophes, params);
            } else {
                message = msgPattern;
            }
        } catch (Exception e) {
            message = "MISSING_" + key + "_MISSING";
        }
        return message;
    }

    public ObjectMappingConverter getObjectMappingConverter() {
        return objectMappingConverter;
    }

    public void setObjectMappingConverter(ObjectMappingConverter objectMappingConverter) {
        this.objectMappingConverter = objectMappingConverter;
    }
}
